package com.anolesoft.yr.mbus.cont.service.impl;

import cn.hutool.core.util.StrUtil;
import com.anolesoft.common.core.web.domain.AjaxResult;
import com.anolesoft.yr.mbus.cont.entity.*;
import com.anolesoft.yr.mbus.cont.entity.ContListService;
import com.anolesoft.yr.mbus.cont.service.*;
import com.anolesoft.yr.mbus.part.entity.PartModelDO;
import com.anolesoft.yr.mbus.part.mapper.PartModelMapper;
import com.anolesoft.yr.store.stk.util.StringUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class ContMainApproveServiceImpl implements ContMainApproveService {
    private ContVariableService contVariableService;
    private ContWordCreatService contWordCreatService;
    private ContMainService contMainService;
    private ContContentService contContentService;
    private PartModelMapper partModelMapper;
    private com.anolesoft.yr.mbus.cont.service.ContListService contListService;
    private ContListServiceService contListServiceService;
    private ContPaymentService contPaymentService;
    @Override
    public AjaxResult getForApprove(String objuid) {
        List<ContVariable> contVariables = contVariableService.selectByExample(new ContVariableExample());
        Map<String, String> contValues = contWordCreatService.getContValue(contMainService.getById(objuid),contVariables);
        ContContentExample contContentExample = new ContContentExample();
        contContentExample.createCriteria().andContMainUidEqualTo(objuid);
        List<ContContent> contContents = contContentService.selectByExample(contContentExample);
        List<ContContent> start = contContents.stream().filter(a -> a.getParentUid() == null || "".equals(a.getParentUid())).sorted(Comparator.comparingInt(ContContent::getOrderCode)).collect(Collectors.toList());
        //递归排序，将所有的内容的order填写上对应的数字，将树形数据展开
        contWordCreatService.contContentSort(start, contContents, new AtomicInteger());
        //重新按照order排序
        contContents = contContents.stream().sorted(Comparator.comparingDouble(ContContent::getOrder)).collect(Collectors.toList());
        for (ContContent value : contContents) {
            String content = value.getContent()==null?"":value.getContent();
            List<String> variable = StringUtil.getVariable(content);
            for (String s : variable) {
                if (contValues.containsKey(s)) {
                    content = content.replace("${" + s + "}", contValues.get(s));
                }
            }
            value.setContent(content);
        }
        ArrayList<ContContent> resultContContent = Lists.newArrayList(contContents);


        for (ContContent contContent : contContents) {
            if (StringUtil.getVariable(contContent.getContent()).size() > 0) {
                List<String> variable = StringUtil.getVariable(contContent.getContent());
                variable.forEach(a -> {
                    if (TableType.PRODUCT_TABLE.equals(a)) {
                        //生成基础的table标签
                        QueryWrapper<ContList> queryWrapper = new QueryWrapper<>();
                        queryWrapper.lambda().eq(ContList::getContMainUid, objuid);
                        List<ContList> contLists = contListService.list(queryWrapper);
                        List<PartModelDO> partModelDOS = Lists.newArrayList();
                        if(contLists.size()>0){
                            partModelDOS= partModelMapper.selectInId(contLists.stream().map(ContList::getBomUid).collect(Collectors.toList()));

                        }
                        Map<String, List<ContList>> collect = contLists.stream().collect(Collectors.groupingBy(ContList::getProdProductUid));
                        QueryWrapper<com.anolesoft.yr.mbus.cont.entity.ContListService> serviceQueryWrapper = new QueryWrapper<>();
                        serviceQueryWrapper.lambda().eq(com.anolesoft.yr.mbus.cont.entity.ContListService::getContMainUid, objuid);
                        List<com.anolesoft.yr.mbus.cont.entity.ContListService> list = contListServiceService.list(serviceQueryWrapper);
                        //处理各种类型的表格
                        List<PartModelDO> finalPartModelDOS = partModelDOS;
                        collect.keySet().forEach(b -> {
                            try {
                                Element element = DocumentHelper.parseText("<table></table>").getRootElement();
                                List<ContList> contListsTemp = collect.get(b);
                                List<String> titleList = Lists.newArrayList();
                                if (b.contains("备件")) {
                                    titleList.addAll(TableType.SPARE_HEADER);
                                } else {
                                    titleList.addAll(TableType.SELL_HEADER);
                                }
                                if (contListsTemp.size() > 0) {
                                    titleList.addAll(list.stream().filter(temp -> temp.getContListUid().equals(contListsTemp.get(0).getObjuid())).map(com.anolesoft.yr.mbus.cont.entity.ContListService::getServiceOption).collect(Collectors.toList()));
                                }
                                Element trHeaderElement = DocumentHelper.parseText("<tr></tr>").getRootElement();
                                for (String s : titleList) {
                                    trHeaderElement.add(DocumentHelper.parseText("<td>" + s + "</td>").getRootElement());
                                }
                                element.add(trHeaderElement);
                                for (int i = 0; i < contListsTemp.size(); i++) {
                                    ContList contList = contListsTemp.get(i);
                                    try {
                                        Element trElement = DocumentHelper.parseText("<tr></tr>").getRootElement();

                                        for (String headName : titleList) {
                                            PartModelDO part = finalPartModelDOS.stream().filter(temp -> temp.getObjuid().equals(contList.getBomUid())).collect(Collectors.toList()).get(0);
                                            switch (headName) {
                                                case TableType.HEADER_QUANTITY:
                                                    trElement.add(DocumentHelper.parseText("<td>" + contList.getQuantity() + "</td>").getRootElement());
                                                    break;
                                                case TableType.HEADER_MODEL:
                                                    trElement.add(DocumentHelper.parseText("<td>" + part.getPartModel() + "</td>").getRootElement());
                                                    break;
                                                case TableType.HEADER_ORDER:
                                                    trElement.add(DocumentHelper.parseText("<td>" + (i+1) + "</td>").getRootElement());
                                                    break;
                                                case TableType.HEADER_PRICE:
                                                    trElement.add(DocumentHelper.parseText("<td>" + contList.getPrice() + "</td>").getRootElement());
                                                    break;
                                                case TableType.HEADER_BRAND:
                                                    trElement.add(DocumentHelper.parseText("<td>" + part.getPartBrand() + "</td>").getRootElement());
                                                    break;
                                                default:
                                                    Map<String, String> serviceMap = list.stream().filter(service -> service.getContListUid().equals(contList.getObjuid())).collect(Collectors.toMap(com.anolesoft.yr.mbus.cont.entity.ContListService::getServiceOption, com.anolesoft.yr.mbus.cont.entity.ContListService::getServiceOptionValue));
                                                    if (serviceMap.containsKey(headName)) {
                                                        trElement.add(DocumentHelper.parseText("<td>" + serviceMap.get(headName) + "</td>").getRootElement());
                                                    } else {
                                                        trElement.add(DocumentHelper.parseText("<td></td>").getRootElement());
                                                    }
                                                    break;
                                            }
                                        }
                                        element.add(trElement);

                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                                ContContent copy = contContent.createCopy();
                                copy.setContent(element.asXML());
                                resultContContent.add(resultContContent.indexOf(contContent),copy);
                            } catch (DocumentException e) {
                                e.printStackTrace();
                            }

                            contContent.setContent(contContent.getContent().replace("${"+TableType.PRODUCT_TABLE+"}",""));

                        });
                    } else if (TableType.PAYMENT_TABLE.equals(a)) {
                        contContent.setContent(contContent.getContent().replace("${"+TableType.PAYMENT_TABLE+"}",""));
                        QueryWrapper<ContPayment> queryWrapper = new QueryWrapper<>();
                        queryWrapper.lambda().eq(ContPayment::getContMainUid, objuid);
                        List<ContPayment> list = contPaymentService.list(queryWrapper);
                        List<String> header = Lists.newArrayList(TableType.PAYMENT_HEADER);

                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        try {
                            Element element = DocumentHelper.parseText("<table></table>").getRootElement();
                            Element trHeaderElement = DocumentHelper.parseText("<tr></tr>").getRootElement();

                            for (String s : header) {
                                Element tdElement = DocumentHelper.parseText("<td>" + s + "</td>").getRootElement();
                                trHeaderElement.add(tdElement);
                            }
                            element.add(trHeaderElement);
                            for (int i = 0; i < list.size(); i++) {
                                Element trElement = DocumentHelper.parseText("<tr></tr>").getRootElement();
                                String date = "";
                                if (list.get(i).getPlanPaymentTime()!=null){
                                    date= simpleDateFormat.format(list.get(i).getPlanPaymentTime());
                                }
                                for (int j = 0; j < TableType.PAYMENT_HEADER.size(); j++) {
                                    switch (TableType.PAYMENT_HEADER.get(j)) {
                                        case TableType.HEADER_PAYMENT:
                                            trElement.add(DocumentHelper.parseText("<td>" + StrUtil.nullToEmpty(list.get(i).getPlanAmount()+"") + "</td>").getRootElement());
                                            break;
                                        case TableType.HEADER_ORDER:
                                            trElement.add(DocumentHelper.parseText("<td>" + (i+1) + "</td>").getRootElement());
                                            break;
                                        case TableType.HEADER_DATE:
                                            trElement.add(DocumentHelper.parseText("<td>" + date+ "</td>").getRootElement());
                                            break;
                                        default:
                                            trElement.add(DocumentHelper.parseText("<td> </td>").getRootElement());
                                    }
                                }
                                element.add(trElement);
                            }
                            int index = resultContContent.indexOf(contContent);
                            ContContent copy = contContent.createCopy();
                            copy.setContent(element.asXML());
                            resultContContent.add(index,copy);

                        } catch (DocumentException e) {
                            e.printStackTrace();
                        }

                    }
                });
            }
        }
        for (int i = 0; i < resultContContent.size(); i++) {
            resultContContent.get(i).setOrder(i);

        }
        resultContContent.forEach(a->{
            a.setContent("<div>"+a.getContent()+"</div>");
        });
        resultContContent.forEach(a->{
            setLvl(resultContContent,a,new AtomicInteger(),a);
        });
        resultContContent.forEach(a->{
            try {
                Element rootElement = DocumentHelper.parseText(a.getContent().replaceAll("&nbsp;","")).getRootElement();

                if ( ItemType.CONTENT.equals( a.getItemType())){

                    rootElement.addAttribute("class","content_"+a.getLvl());
                }else if (ItemType.TITLE.equals(a.getItemType())){
                    rootElement.addAttribute("class","title_"+a.getLvl());
                }
                a.setContent(rootElement.asXML());
            }catch (Exception e){
                e.printStackTrace();
            }

        });
        List<ContContent> contContentTitleList = resultContContent.stream().filter(a -> ItemType.TITLE.equals(a.getItemType()) && a.getLvl() == 0 && PageType.CONTENT_PAGE.equals(a.getPageType())).sorted(Comparator.comparingDouble(ContContent::getOrder)).collect(Collectors.toList());
        AtomicInteger pre = new AtomicInteger() ;
        if (contContentTitleList.size()>0){
            pre.set(contContentTitleList.get(0).getOrderCode()-1);
        }
        contContentTitleList.forEach(a->{
            a.setOrderCode(Byte.parseByte(a.getOrderCode().intValue() - pre.get()+""));
        });
        resultContContent.forEach(a->{
            if (ItemType.TITLE.equals(a.getItemType())&&PageType.CONTENT_PAGE.equals(a.getPageType())){
                setContentTitleNumber(resultContContent,a,a,Lists.newArrayList());
            }else if(ItemType.TITLE.equals(a.getItemType())&&PageType.LAST_PAGE.equals(a.getPageType())){
                setLastPateTitleNumber(resultContContent,a,a,Lists.newArrayList());
            }
        });


//付款计划
        QueryWrapper<ContPayment> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ContPayment::getContMainUid, objuid);
        List<ContPayment> list = contPaymentService.list(queryWrapper);
        List<String> header = Lists.newArrayList(TableType.PAYMENT_HEADER);

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Element element = DocumentHelper.parseText("<table></table>").getRootElement();
            Element trHeaderElement = DocumentHelper.parseText("<tr></tr>").getRootElement();

            for (String s : header) {
                Element tdElement = DocumentHelper.parseText("<td>" + s + "</td>").getRootElement();
                trHeaderElement.add(tdElement);
            }
            element.add(trHeaderElement);
            for (int i = 0; i < list.size(); i++) {
                Element trElement = DocumentHelper.parseText("<tr></tr>").getRootElement();
                String date = "";
                if (list.get(i).getPlanPaymentTime()!=null){
                    date= simpleDateFormat.format(list.get(i).getPlanPaymentTime());
                }
                for (int j = 0; j < TableType.PAYMENT_HEADER.size(); j++) {
                    switch (TableType.PAYMENT_HEADER.get(j)) {
                        case TableType.HEADER_PAYMENT:
                            trElement.add(DocumentHelper.parseText("<td>" + StrUtil.nullToEmpty(list.get(i).getPlanAmount()+"") + "</td>").getRootElement());
                            break;
                        case TableType.HEADER_ORDER:
                            trElement.add(DocumentHelper.parseText("<td>" + (i+1) + "</td>").getRootElement());
                            break;
                        case TableType.HEADER_DATE:
                            trElement.add(DocumentHelper.parseText("<td>" + date+ "</td>").getRootElement());
                            break;
                        default:
                            trElement.add(DocumentHelper.parseText("<td> </td>").getRootElement());
                    }
                }
                element.add(trElement);
            }
            ContContent build = ContContent.builder().content(element.asXML()).pageType(PageType.PAYMENT_PAGE).build();
            resultContContent.add(build);

        } catch (DocumentException e) {
            e.printStackTrace();
        }




        Map<String, List<ContContent>> collect = resultContContent.stream().collect(Collectors.groupingBy(ContContent::getPageType));

        return AjaxResult.success(collect);
    }

    public void setLvl(List<ContContent> lists,ContContent contContent,AtomicInteger i ,ContContent key){
        Map<String, ContContent> collect = lists.stream().collect(Collectors.toMap(ContContent::getObjuid, a -> a));
        if (collect.containsKey(contContent.getParentUid())){
            i.getAndAdd(1);
            setLvl(lists,collect.get(contContent.getParentUid()),i,key);
        }else{
            if (ItemType.CONTENT.equals(key.getItemType())){
                key.setLvl(i.get() == 0 ? 0: i.get()-1);
            }else{
                key.setLvl(i.get());
            }
        }
    }
    //增加 1.合理 中的1.
    public void setContentTitleNumber(List<ContContent> lists, ContContent contContent, ContContent key, List<Integer> list){
        Map<String, ContContent> collect = lists.stream().collect(Collectors.toMap(ContContent::getObjuid, a -> a));
        if (collect.containsKey(contContent.getParentUid())){
            list.add(0,collect.get(contContent.getParentUid()).getOrderCode().intValue());
            setContentTitleNumber(lists,collect.get(contContent.getParentUid()),key,list);
        }else{
            try{
                Element rootElement =DocumentHelper.parseText(key.getContent()).getRootElement();
                Element p = rootElement.element("p");
                if (p!=null){
                    List<Node> content = p.content();
                    Element element = DocumentHelper.createElement("span");
                    element.addAttribute("class","title_number");
                    StringBuffer stringBuffer = new StringBuffer();

                    if (list.size()>0){
                        for (int j = 0; j < list.size(); j++) {
                            if (j==0){
                                stringBuffer.append(list.get(j)+".");
                            }else{
                                stringBuffer.append((list.get(j)+1+"."));
                            }
                        }
                        stringBuffer.append(key.getOrderCode().intValue()+1);
                    }else{
                        stringBuffer.append(key.getOrderCode().intValue());
                    }
                    element.setText(stringBuffer.toString()+"   ");
                    content.add(0,element);
                }

                key.setContent(rootElement.asXML());
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    public void setLastPateTitleNumber(List<ContContent> lists, ContContent contContent, ContContent key, List<Integer> list){
        Map<String, ContContent> collect = lists.stream().collect(Collectors.toMap(ContContent::getObjuid, a -> a));
        if (collect.containsKey(contContent.getParentUid())){
            list.add(0,collect.get(contContent.getParentUid()).getOrderCode().intValue());
            setLastPateTitleNumber(lists,collect.get(contContent.getParentUid()),key,list);
        }else{
            try{
                Element rootElement =DocumentHelper.parseText(key.getContent()).getRootElement();
                Element p = rootElement.element("p");
                if (p!=null){
                    List<Node> content = p.content();
                    Element element = DocumentHelper.createElement("span");
                    StringBuffer stringBuffer = new StringBuffer();

                    if (list.size()>0){
                        for (int j = 0; j < list.size(); j++) {
                            if (j==0){
                                stringBuffer.append(list.get(j)+".");
                            }else{
                                stringBuffer.append((list.get(j)+1)+".");

                            }
                        }

                    }

                    element.setText(stringBuffer.toString()+"   ");
                    content.add(0,element);
                }

                key.setContent(rootElement.asXML());
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}
